# Import required modules
import os
import sys
import json
from typing import List, Dict, Any, Optional, Tuple

# Add project root directory to system path
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.abspath(os.path.join(current_dir, ".."))
sys.path.append(project_root)

# Import local classes
from Course.Course import Course
from User.Teacher import Teacher
from System.UserSystem import UserSystem
from System.AssignmentSystem import AssignmentSystem

# Course management system for handling creation, query, update and deletion of courses
class CourseSystem:    
    def __init__(self, course_data_path, assignment_system=None):
        self.course_data_path = course_data_path
        self.user_system = UserSystem("Data/UserAccount.json")
        self.assignment_system = assignment_system
        self.assignments_json_path = "Data/Assignment.json"
        self.courses = {}
        self._load_courses()
    
    def _load_courses(self):
        # Load course data from JSON file and create Course objects
        try:
            if os.path.exists(self.course_data_path):
                with open(self.course_data_path, 'r', encoding='utf-8') as f:
                    course_data_list = json.load(f)
                
                for course_data in course_data_list:
                    # Get teacher object
                    per_teacher = self.user_system.get_user_by_id(
                        course_data['teacher_id'], 
                        role_filter=["Teacher"]
                    )
                    if not hasattr(per_teacher, 'role') or per_teacher.role != "Teacher":
                        raise ValueError(f"Teacher ID {course_data['teacher_id']} is not a valid Teacher instance")
                    
                    # Create course object
                    course = Course(
                        ID=course_data['id'],
                        Teacher=per_teacher,
                        CourseName=course_data['name'],
                        CourseTime=course_data['time'],
                        Classroom=course_data['classroom'],
                        Students=[],
                        Assignments=course_data.get('assignments', []),
                        introduction=course_data.get('introduction', '')  # Load course introduction
                    )
                    
                    self.courses[course.ID] = course
                
                print(f"Successfully loaded {len(self.courses)} courses")
            else:
                # Initialize empty course system when file doesn't exist
                self.courses = {}
                print(f"Course data file not found, initialized empty course system")
                
        except json.JSONDecodeError:
            # Attempt to create empty file
            try:
                with open(self.course_data_path, 'w', encoding='utf-8') as f:
                    json.dump([], f, ensure_ascii=False, indent=2)
                self.courses = {}
                print(f"Course data file format error, created empty file")
            except Exception as e:
                raise ValueError(f"Course data file format error and cannot create new file: {str(e)}")
        except KeyError as e:
            raise ValueError(f"Course data missing required field: {str(e)}")
        except Exception as e:
            print(f"Error loading courses: {str(e)}")
    
    def get_course_by_id(self, course_id) -> Optional[Course]:
        # Get course object by course ID
        return self.courses.get(course_id)
    
    def get_all_courses(self) -> List[Course]:
        # Get list of all courses
        return list(self.courses.values())
    
    def batch_create_courses(self, course_data_list) -> Tuple[int, List[Dict]]:
        # Batch create courses and save to file
        success_count = 0
        failed_courses = []
        
        for idx, course_data in enumerate(course_data_list):
            try:
                required_fields = ['id', 'name', 'teacher_id', 'time', 'classroom']
                for field in required_fields:
                    if field not in course_data:
                        raise ValueError(f"Missing required field: {field}")
                
                if course_data['id'] in self.courses:
                    raise ValueError(f"Course ID already exists: {course_data['id']}")
                
                # Get and validate teacher
                teacher = self.user_system.get_user_by_id(
                    course_data['teacher_id'], 
                    role_filter=["Teacher"]
                )
                
                if not hasattr(teacher, 'role') or teacher.role != "Teacher":
                    raise ValueError(f"Teacher does not exist or is not a teacher role: {course_data['teacher_id']}")
                
                # Create course
                course = Course(
                    ID=course_data['id'],
                    Teacher=teacher,
                    CourseName=course_data['name'],
                    CourseTime=course_data.get('time', ''),
                    Classroom=course_data.get('classroom', ''),
                    Students=[],
                    Assignments=course_data.get('assignments', []),
                    introduction=course_data.get('introduction', '')  # Load course introduction
                )
                
                self.courses[course.ID] = course
                success_count += 1
                
                # Update teacher's course list
                teacher.Courses.append(course.ID)
                self.user_system.update_user(user_id=teacher.ID, new_courses=teacher.Courses)
                
            except Exception as e:
                failed_courses.append({
                    "index": idx,
                    "course_id": course_data.get('id', f"unknown_ID_{idx}"),
                    "error": str(e)
                })
        
        self._save_courses()
        return success_count, failed_courses
    
    def _save_courses(self):
        # Save course data to JSON file
        course_data_list = []
        for course in self.courses.values():
            course_data = {
                "id": course.ID,
                "name": course.CourseName,
                "teacher_id": course.Teacher.ID,
                "time": course.CourseTime,
                "classroom": course.Classroom,
                "assignments": [a for a in course.Assignments],
                "introduction": course.introduction  # Save course introduction
            }
            course_data_list.append(course_data)
        
        try:
            with open(self.course_data_path, 'w', encoding='utf-8') as f:
                json.dump(course_data_list, f, ensure_ascii=False, indent=2)
            print(f"Course data saved successfully, {len(course_data_list)} courses total")
        except Exception as e:
            print(f"Saving failed: {str(e)}")
    
    def CreateCourse(self, ID, Teacher, CourseName, CourseTime, Classroom, Students=None, Assignments=None, introduction="") -> Course:
        # Create a single course
        if ID in self.courses:
            raise ValueError(f"Course ID already exists: {ID}")
        
        if Students is None:
            Students = []
        if Assignments is None:
            Assignments = []
        
        course = Course(
            ID=ID,
            Teacher=Teacher,
            CourseName=CourseName,
            CourseTime=CourseTime,
            Classroom=Classroom,
            Students=Students,
            Assignments=Assignments,
            introduction=introduction  # Course introduction parameter
        )
        
        Teacher.Courses.append(course.ID)
        self.user_system.update_user(user_id=Teacher.ID, new_courses=Teacher.Courses)
        
        self.courses[ID] = course
        self._save_courses()  # Ensure save after creation
        return course
    
    def UpdateCourse(self, course_id, **kwargs) -> Course:
        # Update course information and save
        course = self.get_course_by_id(course_id)
        if not course:
            raise ValueError(f"Course ID does not exist: {course_id}")
        
        # Update course attributes
        if 'CourseName' in kwargs:
            course.CourseName = kwargs['CourseName']
        if 'CourseTime' in kwargs:
            course.CourseTime = kwargs['CourseTime']
        if 'Classroom' in kwargs:
            course.Classroom = kwargs['Classroom']
        if 'Teacher' in kwargs:
            if not hasattr(kwargs['Teacher'], 'role') or kwargs['Teacher'].role != "Teacher":
                raise ValueError("Teacher must have 'role' attribute set to 'Teacher'")
            course.Teacher = kwargs['Teacher']
        if 'Assignments' in kwargs:
            course.Assignments = kwargs['Assignments']
        if 'introduction' in kwargs:
            course.introduction = kwargs['introduction']  # Update course introduction
        
        self._save_courses()  # Save immediately after update
        return course
    
    def DeleteCourse(self, course_id: str) -> bool:
        # Delete course and associated assignments
        if not isinstance(course_id, str):
            raise TypeError("course_id must be a string")
        
        if course_id not in self.courses:
            return False
        
        per_course = self.get_course_by_id(course_id)
        
        try:
            # Delete associated assignments
            course_assignment_ids = per_course.Assignments or []
            if course_assignment_ids and os.path.exists(self.assignments_json_path):
                with open(self.assignments_json_path, 'r', encoding='utf-8') as f:
                    all_assignments = json.load(f)
                
                remaining_assignments = [
                    assignment for assignment in all_assignments
                    if assignment.get('id') not in course_assignment_ids
                ]
                
                with open(self.assignments_json_path, 'w', encoding='utf-8') as f:
                    json.dump(remaining_assignments, f, ensure_ascii=False, indent=2)
                
                print(f"Deleted {len(course_assignment_ids)} assignment records from assignment file")
            
            # Remove from teacher's and student's course list
            per_course.Teacher.Courses = [cid for cid in per_course.Teacher.Courses if cid != course_id]
            self.user_system.update_user(user_id=per_course.Teacher.ID, new_courses=per_course.Teacher.Courses)
            self.user_system.remove_course_from_students(course_id=per_course.ID)
            # Delete the course itself
            del self.courses[course_id]
            self._save_courses()
            return True
            
        except Exception as e:
            print(f"Error deleting course: {str(e)}")
            return False
    
    def AddStudentToCourse(self, course_id: str, student_id: str) -> Tuple[bool, str]:
        # Add student to course
        # Get student object
        per_student = self.user_system.get_user_by_id(student_id, role_filter=["Student"])
        if not per_student:
            return False, f"Student ID {student_id} does not exist or is not a student role"
        
        # Check if already in course
        if course_id in per_student.Courses:
            return False, "Student is already in the course"
        
        # Add course and update
        per_student.Courses.append(course_id)
        success, msg = self.user_system.update_user(
            user_id=student_id, 
            new_courses=per_student.Courses
        )
        
        if success:
            return True, f"Successfully added student {student_id} to course {course_id}"
        else:
            return False, f"Failed to add student: {msg}"
    
    def RemoveStudentFromCourse(self, course_id: str, student_id: str) -> Tuple[bool, str]:
        # Remove student from course
        # Get student object
        per_student = self.user_system.get_user_by_id(student_id, role_filter=["Student"])
        if not per_student:
            return False, f"Student ID {student_id} does not exist or is not a student role"
        
        # Check if student is in course
        if course_id not in per_student.Courses:
            return False, "Student is not in the course"
        
        # Remove course ID from student's course list
        per_student.Courses.remove(course_id)
        success, msg = self.user_system.update_user(
            user_id=student_id, 
            new_courses=per_student.Courses
        )
        
        if success:
            return True, f"Successfully removed student {student_id} from course {course_id}"
        else:
            return False, f"Failed to remove student: {msg}"
    
    def GetStudentsInCourse(self, course_id: str) -> List[str]:
        # Get all student IDs in a course
        all_students = []
        for user_data in self.user_system.get_all_users():
            if user_data.get("role") == "Student" and course_id in user_data.get("courses", []):
                all_students.append(user_data["id"])
        return all_students